package com.xbongbong.pro.statistic.service.result;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.Arith;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.DateUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.pro.domain.entity.ChartEntity;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.statistic.constant.ChartI18Constant;
import com.xbongbong.pro.statistic.enums.PanoramaEnum;
import com.xbongbong.pro.statistic.enums.SystemCodeEnum;
import com.xbongbong.pro.statistic.enums.ValueTypeEnum;
import com.xbongbong.pro.statistic.result.pojo.CallLogAggsPojo;
import com.xbongbong.pro.statistic.result.pojo.ChartResultPojo;
import com.xbongbong.pro.statistic.result.pojo.ElasticAggsPojo;
import com.xbongbong.pro.statistic.result.pojo.PanoramaPojo;
import com.xbongbong.pro.statistic.result.pojo.TotalAndAggPojo;
import com.xbongbong.pro.statistic.result.pojo.vo.ChartResultDetailVO;
import com.xbongbong.pro.statistic.result.pojo.vo.ResultDataTableVO;
import com.xbongbong.pro.statistic.result.pojo.vo.ResultTableVO;
import com.xbongbong.pro.statistic.through.pojo.dto.ThroughDTO;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.enums.CallCenterCallLogCallSourceEnum;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.metrics.SumAggregationBuilder;
import org.elasticsearch.search.aggregations.support.ValuesSourceAggregationBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.rangeQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.elasticsearch.index.query.QueryBuilders.termsQuery;

/**
 * @author youli.chen
 * @version v1.0
 * @description: 通话记录相关统计
 * @date 2019/3/6 21:16
 * @since v1.0
 */
@Component
public class CrmCallLogResult extends ChartResultParentService implements ChartResultSystem, PanoramaResult {
    private static final Logger LOG = LoggerFactory.getLogger(CrmCallLogResult.class);

    /**
     * 系统指标公共接口
     *
     * @param chartResultPojo     请求系统指标接口需要用到的pojo类（内部存系统指标统计时需要的参数）
     * @param chartResultDetailVO 统计需要渲染的图（表---可能同时存在，可能某一个存在）塞入该vo
     * @return java.util.Objects 塞入过统计结果的chartResultDetailVO
     * @throws XbbException
     * @author youli.chen
     * @date 2019/2/14 10:23
     * @version v1.0
     * @since v1.0
     */
    @Override
    public Object getTarget(ChartResultPojo chartResultPojo, ChartResultDetailVO chartResultDetailVO) throws XbbException {
        SystemCodeEnum systemCodeEnum = chartResultPojo.getSystemCodeEnum();
        switch (systemCodeEnum) {
            // 呼出统计分析
            case CALL_OUTBOUND:
                return callLogTotal(chartResultPojo, chartResultDetailVO, true);
            // 呼入统计分析
            case CALL_INBOUND:
                return callLogTotal(chartResultPojo, chartResultDetailVO, false);
            // 个人今日呼入统计分析
            case OWN_CALL_OUTBOUND:
                return callLogToDay(chartResultPojo, chartResultDetailVO);
            default:
                break;
        }
        return null;
    }

    @Override
    public Object getValueTarget(ChartResultPojo chartResultPojo) {
        return null;
    }

    @Override
    public Object customer(PanoramaPojo panoramaPojo) throws XbbException {
        PanoramaEnum panoramaEnum = panoramaPojo.getPanoramaEnum();
        switch (panoramaEnum) {
            case CUSTOMER_CALL_COUNT:
                return panoramaCustomerCallCount(panoramaPojo);
            case CUSTOMER_CALL_LOG_TIME:
                return panoramaCustomerCallLogTime(panoramaPojo);
            case CUSTOMER_CALL_LOG_TIME_RATE:
                return panoramaCustomerCallLogTimeRate(panoramaPojo);
            default:
                break;
        }
        return null;
    }

    /**
     * 呼叫统计
     *
     * @param chartResultPojo
     * @param chartResultDetailVO
     * @param outOrIn             true: 呼出  false：呼入
     * @return java.lang.Object
     * @throws XbbException
     * @author youli.chen
     * @date 2019/2/19 20:15
     * @version v1.0
     * @since v1.0
     */
    public Object callLogTotal(ChartResultPojo chartResultPojo, ChartResultDetailVO chartResultDetailVO, boolean outOrIn) throws XbbException {

        // 呼叫次数数据封装
        ElasticAggsPojo elasticAggsPojo = callLogTotal2ElasticAggsPojo(chartResultPojo, ValueTypeEnum.ARRAY_TYPE, outOrIn);
        String legend;
        if (outOrIn) {
            legend = I18nMessageUtil.getMessage(ChartI18Constant.CALL_THE_NUMBER_CONTENT);
        } else {
            legend = I18nMessageUtil.getMessage(ChartI18Constant.NUMBER_OF_CALLS_CONTENT);
        }
        Boolean totalFlag = false;
        String valueTitle = "";
        String unit = "";


        ThroughDTO throughDTO = null;
        //是否画入表格内 0否1是
        Integer tableFlag = 1;
        chartResultDetailVO = systemChartHelp.packageResult4One(elasticAggsPojo, chartResultPojo, chartResultDetailVO, throughDTO, tableFlag, legend, unit, totalFlag, valueTitle);

        if (chartResultDetailVO.getTable() == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, "暂无通话记录");
        }
        ResultTableVO resultTableVO = chartResultDetailVO.getTable();
        //设置表的名称,导出用
        setTableName(resultTableVO, chartResultPojo);
        List<List<ResultDataTableVO>> data = resultTableVO.getData();

        // 通话时长统计
        List<List<ResultDataTableVO>> tableTimeVOList = callLogTimeTotal(chartResultPojo, outOrIn);
        // 通话成功数
        List<List<ResultDataTableVO>> tableSuccessVOList = callLogSuccessTotal(chartResultPojo, outOrIn);
        // 呼叫坐席数
        List<List<ResultDataTableVO>> tableAgentVOList = callLogAgentTotal(chartResultPojo, outOrIn);
        // 呼叫成功率
        List<List<ResultDataTableVO>> tableSuccessRateVOList = callLogSuccessRateTotal(chartResultPojo, tableSuccessVOList, data, outOrIn);
        // 人均呼叫次数
        List<List<ResultDataTableVO>> tablePersonRateVOList = callLogPersonRateTotal(chartResultPojo, data, tableAgentVOList, outOrIn);
        // 组装数据
        data.add(tableTimeVOList.get(0));
        data.add(tableSuccessVOList.get(0));
        data.add(tableAgentVOList.get(0));
        data.add(tableSuccessRateVOList.get(0));
        data.add(tablePersonRateVOList.get(0));

        return chartResultDetailVO;
    }

    /**
     * 呼叫次数，计算当前的方法，主要用于【呼叫次数的统计】
     *
     * @param chartResultPojo 参数pojo
     * @param valueTypeEnum   数值类型
     * @return com.xbongbong.paas.elasticsearch.pojo.vo.ElasticAggsPojo
     * @throws XbbException
     * @author youli.chen
     * @date 2019/2/20 9:49
     * @version v1.0
     * @since v1.0
     */
    private ElasticAggsPojo callLogTotal2ElasticAggsPojo(ChartResultPojo chartResultPojo, ValueTypeEnum valueTypeEnum, boolean outOrIn) throws XbbException {
        /*--------处理查询条件--------*/
        BoolQueryBuilder boolQueryBuilder = chartQueryHelp.callLogQuery(chartResultPojo, outOrIn);

        String fieldTime = "addTime";
        ElasticAggsPojo elasticAggsPojo = systemChartHelp.getCount4Agg(chartResultPojo, valueTypeEnum,
                IndexTypeEnum.IDX_CALL_CENTER_CALL_LOG, boolQueryBuilder, fieldTime);

        return elasticAggsPojo;
    }

    /**
     * 呼出时长
     *
     * @param chartResultPojo 获取图表结果参数pojo
     * @param outOrIn         true: 呼出  false：呼入
     * @return java.lang.Object
     * @throws XbbException
     * @author youli.chen
     * @date 2019/2/19 20:15
     * @version v1.0
     * @since v1.0
     */
    public List<List<ResultDataTableVO>> callLogTimeTotal(ChartResultPojo chartResultPojo, boolean outOrIn) throws XbbException {
        // 呼出时长数据封装
        ElasticAggsPojo elasticAggsPojo = callLogTime2ElasticAggsPojo(chartResultPojo, ValueTypeEnum.ARRAY_TYPE, "duration", outOrIn);
        String legend;
        if (outOrIn) {
            legend = I18nMessageUtil.getMessage(ChartI18Constant.OUTGOII1G_TIME_CONTENT);
        } else {
            legend = I18nMessageUtil.getMessage(ChartI18Constant.ANSWERING_TIME_CONTENT);
        }
        String unit = "";
        List<List<ResultDataTableVO>> tableVOList = systemChartHelp.packageResult4TableOne(elasticAggsPojo, chartResultPojo, null, legend, unit);

        // 除去第一个  例如："value":"呼叫次数(次)"
        List<ResultDataTableVO> dataDetail = tableVOList.get(0);
        ResultDataTableVO getDataVO = dataDetail.get(0);
        dataDetail.remove(getDataVO);
        for (ResultDataTableVO tableVO : dataDetail) {
            int callCount = StringUtil.toInt(tableVO.getValue(), 0);
            String secondToTime = DateTimeUtil.secondToTime(callCount);
            tableVO.setValue(secondToTime);
        }
        dataDetail.add(0, getDataVO);
        return tableVOList;
    }

    /**
     * 呼出时长，计算当前的方法，主要用于【呼出时长的统计】
     *
     * @param chartResultPojo 参数pojo
     * @param valueTypeEnum   数值类型
     * @param sumField        求和字段，如呼出时长
     * @return com.xbongbong.paas.elasticsearch.pojo.vo.ElasticAggsPojo
     * @throws XbbException
     * @author youli.chen
     * @date 2019/2/20 9:49
     * @version v1.0
     * @since v1.0
     */
    private ElasticAggsPojo callLogTime2ElasticAggsPojo(ChartResultPojo chartResultPojo, ValueTypeEnum valueTypeEnum,
                                                        String sumField, boolean outOrIn) throws XbbException {
        BoolQueryBuilder boolQueryBuilder = chartQueryHelp.callLogQuery(chartResultPojo, outOrIn);
        String fieldTime = "addTime";
        return systemChartHelp.getInt4Agg(chartResultPojo, valueTypeEnum, IndexTypeEnum.IDX_CALL_CENTER_CALL_LOG, boolQueryBuilder, fieldTime, sumField);
    }


    /**
     * 呼叫成功数
     *
     * @param chartResultPojo 获取图表结果参数pojo
     * @param outOrIn         true: 呼出  false：呼入
     * @return java.lang.Object
     * @throws XbbException
     * @author youli.chen
     * @date 2019/2/19 20:15
     * @version v1.0
     * @since v1.0
     */
    public List<List<ResultDataTableVO>> callLogSuccessTotal(ChartResultPojo chartResultPojo, boolean outOrIn) throws XbbException {
        // 呼叫成功数数据封装
        ElasticAggsPojo elasticAggsPojo = callLogSuccess2ElasticAggsPojo(chartResultPojo, ValueTypeEnum.ARRAY_TYPE, outOrIn);
        String legend;
        if (outOrIn) {
            legend = I18nMessageUtil.getMessage(ChartI18Constant.NUMBER_OF_SUCCESSFUL_CALLS_CONTENT);
        } else {
            legend = I18nMessageUtil.getMessage(ChartI18Constant.NUMBER_OF_SUCCESSFUL_ANSWERS_CONTENT);
        }
        String unit = "";
        List<List<ResultDataTableVO>> tableVOList = systemChartHelp.packageResult4TableOne(elasticAggsPojo, chartResultPojo, null, legend, unit);

        return tableVOList;
    }

    /**
     * 呼叫成功数，计算当前的方法，主要用于【呼叫成功数的统计】
     *
     * @param chartResultPojo 参数pojo
     * @param valueTypeEnum   数值类型
     * @return com.xbongbong.paas.elasticsearch.pojo.vo.ElasticAggsPojo
     * @throws XbbException
     * @author youli.chen
     * @date 2019/2/20 9:49
     * @version v1.0
     * @since v1.0
     */
    private ElasticAggsPojo callLogSuccess2ElasticAggsPojo(ChartResultPojo chartResultPojo, ValueTypeEnum valueTypeEnum, boolean outOrIn) throws XbbException {
        /*--------处理查询条件--------*/
        BoolQueryBuilder boolQueryBuilder = chartQueryHelp.callLogQuery(chartResultPojo, outOrIn);
        // 通话结果，1: 成功；0：失败（度言字段 outcome 呼叫结果，SUCCESS: 成功；FAIL：失败）
        boolQueryBuilder.filter(rangeQuery("result").gte(BasicConstant.ONE).lte(BasicConstant.ONE));

        ElasticAggsPojo elasticAggsPojo = systemChartHelp.getCount4Agg(chartResultPojo, valueTypeEnum,
                IndexTypeEnum.IDX_CALL_CENTER_CALL_LOG, boolQueryBuilder, "addTime");

        return elasticAggsPojo;
    }

    /**
     * 呼叫坐席数
     *
     * @param chartResultPojo 获取图表结果参数pojo
     * @param outOrIn         true: 呼出  false：呼入
     * @return java.lang.Object
     * @throws XbbException
     * @author youli.chen
     * @date 2019/2/19 20:15
     * @version v1.0
     * @since v1.0
     */
    public List<List<ResultDataTableVO>> callLogAgentTotal(ChartResultPojo chartResultPojo, boolean outOrIn) throws XbbException {
        // 呼叫坐席数数据封装
        /*--------处理查询条件--------*/
        BoolQueryBuilder boolQueryBuilder = chartQueryHelp.callLogQuery(chartResultPojo, outOrIn);
        //时间聚合字段
        String fieldTime = "addTime";
        //排重字段
        String fieldGroup = "userId.keyword";

        //用userId聚合结果
        ElasticAggsPojo elasticAggsPojo = systemChartHelp.distinctAggregations(chartResultPojo, ValueTypeEnum.ARRAY_TYPE,
                IndexTypeEnum.IDX_CALL_CENTER_CALL_LOG, boolQueryBuilder, fieldTime, fieldGroup);
        String legend;
        if (outOrIn) {
            legend = I18nMessageUtil.getMessage(ChartI18Constant.NUMBER_OF_CALL_AGENTS_CONTENT);
        } else {
            legend = I18nMessageUtil.getMessage(ChartI18Constant.NUMBER_OF_ANSWERING_AGENTS_CONTENT);
        }
        String unit = "";
        List<List<ResultDataTableVO>> tableVOList = systemChartHelp.packageResult4TableOne(elasticAggsPojo, chartResultPojo, null, legend, unit);

        return tableVOList;
    }

    /**
     * 呼叫成功率
     *
     * @param chartResultPojo    获取图表结果参数pojo
     * @param outOrIn            true: 呼出  false：呼入
     * @param tableSuccessVOList 呼叫成功数
     * @param data               呼叫次数
     * @return java.lang.Object
     * @throws XbbException
     * @author youli.chen
     * @date 2019/2/19 20:15
     * @version v1.0
     * @since v1.0
     */
    public List<List<ResultDataTableVO>> callLogSuccessRateTotal(ChartResultPojo chartResultPojo, List<List<ResultDataTableVO>> tableSuccessVOList,
                                                                 List<List<ResultDataTableVO>> data, boolean outOrIn) throws XbbException {
        // 呼叫成功率数据封装
        List<List<ResultDataTableVO>> resultDataTableVOList = new ArrayList<>();
        List<ResultDataTableVO> resultDataTableVOs = new ArrayList<>();
        String legend;
        if (outOrIn) {
            legend = I18nMessageUtil.getMessage(ChartI18Constant.CALL_SUCCESS_RATE_CONTENT);
        } else {
            legend = I18nMessageUtil.getMessage(ChartI18Constant.ANSWERING_SUCCESS_RATE_CONTENT);
        }
        String unit = "";
        tableTitle(legend, unit, resultDataTableVOs);

        // 除去第一个  例如："value":"呼叫次数(次)"
        List<ResultDataTableVO> tableDetail = tableSuccessVOList.get(0);
        ResultDataTableVO getTableVO = tableDetail.get(0);
        tableDetail.remove(getTableVO);

        List<Double> tableMsg = new ArrayList<>();
        List<Double> dataMsg = new ArrayList<>();

        // 除去第一个  例如："value":"呼叫次数(次)"
        List<ResultDataTableVO> dataDetail = data.get(0);
        ResultDataTableVO getDataVO = dataDetail.get(0);
        dataDetail.remove(getDataVO);

        for (ResultDataTableVO table : tableDetail) {
            tableMsg.add(Double.valueOf(table.getValue()));
        }
        for (ResultDataTableVO table : dataDetail) {
            dataMsg.add(Double.valueOf(table.getValue()));
        }

        for (int i = 0; i < dataDetail.size(); i++) {
            Double tableMsgDetail = tableMsg.get(i);
            Double dataMsgDetail = dataMsg.get(i);

            Double rate = (dataMsgDetail == 0) ? 0 : Arith.div(tableMsgDetail, dataMsgDetail) * 100;
            if (rate > 0) {
                rate = StringUtil.toDouble(StringUtil.formatDouble(rate, 2, 1));
            } else {
                rate = 0.00;
            }
            String num = rate + "%";
            //呼出（呼入）成功率
            ResultDataTableVO resultDataTableVO = new ResultDataTableVO(num, null);
            resultDataTableVOs.add(resultDataTableVO);
        }
        resultDataTableVOList.add(resultDataTableVOs);
        tableDetail.add(0, getTableVO);
        dataDetail.add(0, getDataVO);
        return resultDataTableVOList;
    }


    /**
     * 人均呼叫次数
     *
     * @param chartResultPojo  获取图表结果参数pojo
     * @param data             呼叫次数
     * @param tableAgentVOList 坐席数
     * @param outOrIn          true：呼出  false：呼入
     * @return java.lang.Object
     * @throws XbbException
     * @author youli.chen
     * @date 2019/2/19 20:15
     * @version v1.0
     * @since v1.0
     */
    public List<List<ResultDataTableVO>> callLogPersonRateTotal(ChartResultPojo chartResultPojo, List<List<ResultDataTableVO>> data,
                                                                List<List<ResultDataTableVO>> tableAgentVOList, boolean outOrIn) throws XbbException {
        // 呼叫成功率数据封装
        List<List<ResultDataTableVO>> resultDataTableVOList = new ArrayList<>();
        List<ResultDataTableVO> resultDataTableVOs = new ArrayList<>();
        String legend;
        if (outOrIn) {
            legend = I18nMessageUtil.getMessage(ChartI18Constant.NUMBER_OF_CALLS_PER_CAPITA_CONTENT);
        } else {
            legend = I18nMessageUtil.getMessage(ChartI18Constant.ANSWERS_PER_CAPITA_CONTENT);
        }
        String unit = "";
        tableTitle(legend, unit, resultDataTableVOs);

        // 除去第一个  例如："value":"呼叫次数(次)"
        List<ResultDataTableVO> dataDetail = data.get(0);
        ResultDataTableVO getDataVO = dataDetail.get(0);
        dataDetail.remove(getDataVO);

        // 除去第一个  例如："value":"呼叫次数(次)"
        List<ResultDataTableVO> tableDetail = tableAgentVOList.get(0);
        ResultDataTableVO getTableVO = tableDetail.get(0);
        tableDetail.remove(getTableVO);

        List<Double> tableMsg = new ArrayList<>();
        List<Double> dataMsg = new ArrayList<>();

        for (ResultDataTableVO table : tableDetail) {
            tableMsg.add(Double.valueOf(table.getValue()));
        }
        for (ResultDataTableVO table : dataDetail) {
            dataMsg.add(Double.valueOf(table.getValue()));
        }

        for (int i = 0; i < dataDetail.size(); i++) {
            Double tableMsgDetail = tableMsg.get(i);
            Double dataMsgDetail = dataMsg.get(i);

            Double person = (tableMsgDetail == 0) ? 0 : Arith.div(dataMsgDetail, tableMsgDetail);
            person = StringUtil.toDouble(StringUtil.formatDouble(person, 2, 1));

            String per = Double.toString(person);
            //人均次数
            ResultDataTableVO resultDataTableVO = new ResultDataTableVO(per, null);
            resultDataTableVOs.add(resultDataTableVO);
        }

        resultDataTableVOList.add(resultDataTableVOs);
        tableDetail.add(0, getTableVO);
        dataDetail.add(0, getDataVO);
        return resultDataTableVOList;
    }

    /**
     * 一行数据第一列数据名封装
     *
     * @param legend
     * @param unit
     * @param resultDataTableVOs
     */
    private void tableTitle(String legend, String unit, List<ResultDataTableVO> resultDataTableVOs) {
        List<String> legendList = new ArrayList<>();
        legendList.add(legend);
        List<String> unitList = Arrays.asList(unit);
        for (int i = 0; i < legendList.size(); i++) {
            String perLegend = legendList.get(i);
            if (unitList.size() > i) {
                unit = unitList.get(i);
            }
            //表标题
            String title = StringUtil.isEmpty(unit) ? perLegend : perLegend + "(" + unit + ")";
            ResultDataTableVO resultDataTableTitle = new ResultDataTableVO(title, null);
            resultDataTableVOs.add(resultDataTableTitle);
        }
    }

    /**
     * 个人呼叫统计
     *
     * @param chartResultPojo
     * @param chartResultDetailVO
     * @return java.lang.Object
     * @throws XbbException
     * @author youli.chen
     * @date 2019/2/19 20:15
     * @version v1.0
     * @since v1.0
     */
    public Object callLogToDay(ChartResultPojo chartResultPojo, ChartResultDetailVO chartResultDetailVO) throws XbbException {

        // 呼叫次数数据封装
        ElasticAggsPojo elasticAggsPojo = callLogTotal2ElasticAggsPojo(chartResultPojo, ValueTypeEnum.ARRAY_TYPE);
        String legend = "今日呼叫次数";
        Boolean totalFlag = false;
        String valueTitle = "";
        String unit = "";
        ThroughDTO throughDTO = null;
        //是否画入表格内 0否1是
        Integer tableFlag = 1;
        chartResultDetailVO = systemChartHelp.packageResult4One(elasticAggsPojo, chartResultPojo, chartResultDetailVO, throughDTO, tableFlag, legend, unit, totalFlag, valueTitle);

        ResultTableVO resultTableVO = chartResultDetailVO.getTable();
        setTableName(resultTableVO, chartResultPojo);
        List<List<ResultDataTableVO>> data = resultTableVO.getData();

        // 除去第一个  例如："value":"呼叫次数(次)"
        List<ResultDataTableVO> dataDetail = data.get(0);
        ResultDataTableVO getDataVO = dataDetail.get(0);
        dataDetail.remove(getDataVO);
        int total = 0;
        for (ResultDataTableVO tableVO : dataDetail) {
            int callCount = StringUtil.toInt(tableVO.getValue(), 0);
            total += callCount;
        }
        ResultDataTableVO newTableVO = new ResultDataTableVO(String.valueOf(total), null);
        dataDetail.clear();
        dataDetail.add(0, getDataVO);
        dataDetail.add(newTableVO);
        data.clear();
        data.add(dataDetail);

        // 通话时长统计
        List<List<ResultDataTableVO>> tableTimeVOList = callLogTimeTotal(chartResultPojo);
        // 通话成功数
        List<List<ResultDataTableVO>> tableSuccessVOList = callLogSuccessTotal(chartResultPojo);
        // 组装数据
        data.add(tableTimeVOList.get(0));
        data.add(tableSuccessVOList.get(0));

        return chartResultDetailVO;
    }

    /**
     * 个人呼叫次数，计算当前的方法，主要用于【个人呼叫次数的统计】
     *
     * @param chartResultPojo 参数pojo
     * @param valueTypeEnum   数值类型
     * @return com.xbongbong.paas.elasticsearch.pojo.vo.ElasticAggsPojo
     * @throws XbbException
     * @author youli.chen
     * @date 2019/2/20 9:49
     * @version v1.0
     * @since v1.0
     */
    private ElasticAggsPojo callLogTotal2ElasticAggsPojo(ChartResultPojo chartResultPojo, ValueTypeEnum valueTypeEnum) throws XbbException {
        String corpid = chartResultPojo.getCorpid();
        //不计算未来时间
        int startTime = chartResultPojo.getStartTime();
        int endTime = chartResultPojo.getEndTime();

        /*--------处理查询条件--------*/
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
        boolQueryBuilder.filter(termQuery("del", 0));
        // 呼出：1 ;呼入：0
        boolQueryBuilder.filter(rangeQuery("type").gte(BasicConstant.ONE).lte(BasicConstant.ONE));

        // 登录人
        boolQueryBuilder.filter(termsQuery("userId.keyword", chartResultPojo.getUserId()));

        //时间范围
        boolQueryBuilder.filter(rangeQuery("addTime").gte(startTime).lt(endTime));
        Integer code = CallCenterCallLogCallSourceEnum.CALL_CENTER.getCode();
        boolQueryBuilder.filter(rangeQuery("callSource").gte(code).lte(code));


        ElasticAggsPojo elasticAggsPojo = systemChartHelp.getCount4Agg(chartResultPojo, valueTypeEnum,
                IndexTypeEnum.IDX_CALL_CENTER_CALL_LOG, boolQueryBuilder, "addTime");

        return elasticAggsPojo;
    }

    /**
     * 个人呼出时长
     *
     * @param chartResultPojo 获取图表结果参数pojo
     * @return java.lang.Object
     * @throws XbbException
     * @author youli.chen
     * @date 2019/2/19 20:15
     * @version v1.0
     * @since v1.0
     */
    public List<List<ResultDataTableVO>> callLogTimeTotal(ChartResultPojo chartResultPojo) throws XbbException {
        // 呼出时长数据封装
        ElasticAggsPojo elasticAggsPojo = callLogTime2ElasticAggsPojo(chartResultPojo, ValueTypeEnum.ARRAY_TYPE, "duration", true);
        String legend = "今日呼出时长";
        String unit = "";
        List<List<ResultDataTableVO>> tableVOList = systemChartHelp.packageResult4TableOne(elasticAggsPojo, chartResultPojo, null, legend, unit);

        // 除去第一个  例如："value":"呼叫次数(次)"
        List<ResultDataTableVO> dataDetail = tableVOList.get(0);
        ResultDataTableVO getDataVO = dataDetail.get(0);
        dataDetail.remove(getDataVO);
        int total = 0;
        for (ResultDataTableVO tableVO : dataDetail) {
            int callCount = StringUtil.toInt(tableVO.getValue(), 0);
            total += callCount;
        }
        String secondToTime = DateTimeUtil.secondToTime(total);
        ResultDataTableVO newTableVO = new ResultDataTableVO(secondToTime, null);
        dataDetail.clear();
        dataDetail.add(0, getDataVO);
        dataDetail.add(newTableVO);
        tableVOList.clear();
        tableVOList.add(dataDetail);

        return tableVOList;
    }

    /**
     * 个人呼叫成功数
     *
     * @param chartResultPojo 获取图表结果参数pojo
     * @return java.lang.Object
     * @throws XbbException
     * @author youli.chen
     * @date 2019/2/19 20:15
     * @version v1.0
     * @since v1.0
     */
    public List<List<ResultDataTableVO>> callLogSuccessTotal(ChartResultPojo chartResultPojo) throws XbbException {
        // 呼叫成功数数据封装
        ElasticAggsPojo elasticAggsPojo = callLogSuccess2ElasticAggsPojo(chartResultPojo, ValueTypeEnum.ARRAY_TYPE, true);
        String legend = "今日呼叫成功数";
        String unit = "";
        List<List<ResultDataTableVO>> tableVOList = systemChartHelp.packageResult4TableOne(elasticAggsPojo, chartResultPojo, null, legend, unit);

        // 除去第一个  例如："value":"呼叫次数(次)"
        List<ResultDataTableVO> dataDetail = tableVOList.get(0);
        ResultDataTableVO getDataVO = dataDetail.get(0);
        dataDetail.remove(getDataVO);
        int total = 0;
        for (ResultDataTableVO tableVO : dataDetail) {
            int callCount = StringUtil.toInt(tableVO.getValue(), 0);
            total += callCount;
        }
        ResultDataTableVO newTableVO = new ResultDataTableVO(String.valueOf(total), null);
        dataDetail.clear();
        dataDetail.add(0, getDataVO);
        dataDetail.add(newTableVO);
        tableVOList.clear();
        tableVOList.add(dataDetail);

        return tableVOList;
    }

    /**
     * 客户全景图--通话次数
     * @param panoramaPojo
     * @return java.lang.String
     * @author zcp
     * @date 2019/6/3 16:55
     * @since v1.0
     * @version v1.0
     */
    public String panoramaCustomerCallCount(PanoramaPojo panoramaPojo) throws XbbException {
        BoolQueryBuilder boolQueryBuilder = chartQueryHelp.panoramaQuery4Call(panoramaPojo, panoramaPojo.getDataId());
        ElasticAggsPojo elasticAggsPojo = esHelper.elasticAggs(IndexTypeEnum.IDX_CALL_CENTER_CALL_LOG, boolQueryBuilder, null);
        return elasticAggsPojo.getTotal();
    }

    /**
     * 客户全景图--通话时长
     * @param panoramaPojo
     * @return java.lang.String
     * @author zcp
     * @date 2019/6/3 20:02
     * @since v1.0
     * @version v1.0
     */
    public String panoramaCustomerCallLogTime(PanoramaPojo panoramaPojo) throws XbbException {
        BoolQueryBuilder boolQueryBuilder = chartQueryHelp.panoramaQuery4Call(panoramaPojo, panoramaPojo.getDataId());

        String sumField = "duration";
        TotalAndAggPojo totalAndAggPojo = systemChartHelp.getInt4Total(IndexTypeEnum.IDX_CALL_CENTER_CALL_LOG, boolQueryBuilder, sumField);
        int duration = totalAndAggPojo.getAgg();

        String secondToTime = DateUtil.secondToTimeTip(duration);
        return secondToTime;
    }

    /**
     * 客户全景图--平均时长
     * @param panoramaPojo
     * @return java.lang.String
     * @author zcp
     * @date 2019/6/3 20:03
     * @since v1.0
     * @version v1.0
     */
    public String panoramaCustomerCallLogTimeRate(PanoramaPojo panoramaPojo) throws XbbException {
        BoolQueryBuilder boolQueryBuilder = chartQueryHelp.panoramaQuery4Call(panoramaPojo, panoramaPojo.getDataId());
        String sumField = "duration";
        TotalAndAggPojo totalAndAggPojo = systemChartHelp.getInt4Total(IndexTypeEnum.IDX_CALL_CENTER_CALL_LOG, boolQueryBuilder, sumField);
        int duration = totalAndAggPojo.getAgg();
        int total = totalAndAggPojo.getTotal();

        //平均秒，无需保留小数
        int rate = total == 0 || duration == 0 ? 0 : (int) Arith.div(duration, total);
        String secondToTime = DateUtil.secondToTimeTip(rate);
        return secondToTime;
    }

    /**
     * 设置表名
     *
     * @param resultTableVO 表的结果
     * @param chartResultPojo 入参
     * @author 徐俊杰
     * @date 2019/5/30 15:07
     * @since v1.0
     */
    private void setTableName(ResultTableVO resultTableVO, ChartResultPojo chartResultPojo) {
        ChartEntity chartEntity = chartResultPojo.getChartEntity();
        if (chartEntity != null) {
            //设置表的名称,导出用
            resultTableVO.setTableName(chartEntity.getName());
        } else {
            //在没有chart实体的时候,设置表的名称
            resultTableVO.setTableName(chartResultPojo.getSystemCodeEnum().getName());
        }
    }


    /**
     * 同时sum多个字段（同一级的字段）的结果，并且对聚合结果进行排序，限制了buckets大小为100，比如员工呼出/呼入统计
     * @param sumFieldList 要sum的字段attr，同时也作为其分组key
     * @param fieldAttr 排序字段
     * @param sortType 排序方式
     * @return java.util.List<org.elasticsearch.search.aggregations.support.ValuesSourceAggregationBuilder>
     * @author youli.chen
     * @since v1.0
     * @version v1.0
     */
    public List<CallLogAggsPojo> sumMuchCallAttr4Sort(IndexTypeEnum indexTypeEnum, BoolQueryBuilder boolQueryBuilder, List<String> sumFieldList, String fieldAttr, boolean sortType) throws XbbException {
        List<ValuesSourceAggregationBuilder> aggsList = new ArrayList<>();
        for (String sumField : sumFieldList) {
            //聚合字段和聚合分组的key都使用sumField
            SumAggregationBuilder sumAggregationBuilder = AggregationBuilders.sum(sumField).field(sumField);
            aggsList.add(sumAggregationBuilder);
        }
        JSONObject jsonObject = esHelper.multElasticAggs4Buckets2User(indexTypeEnum, boolQueryBuilder, aggsList, fieldAttr, sortType);
        JSONObject aggregations = jsonObject.getJSONObject("aggregations");

        JSONArray bucketsArray = aggregations.getJSONObject("userId.keyword") == null ? new JSONArray() : aggregations.getJSONObject("userId.keyword").getJSONArray("buckets");
        bucketsArray = bucketsArray == null ? new JSONArray() : bucketsArray;

        List<CallLogAggsPojo> result = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (Object object : bucketsArray) {
            if(object != null){
                JSONObject json = (JSONObject) object;
                String userId = json.getString("key");
                Double callCount = json.getBigDecimal("doc_count").doubleValue();
                Double durationCount = json.getJSONObject("duration").getBigDecimal("value").doubleValue();
                CallLogAggsPojo aggsPojo = new CallLogAggsPojo();
                aggsPojo.setUserId(userId);
                aggsPojo.setCallCount(callCount);
                aggsPojo.setDurationCount(durationCount);
                result.add(aggsPojo);
            }
        }
        return result;
    }


    /**
     * 同时sum多个字段（同一级的字段）的结果
     * @param sumFieldList 要sum的字段attr，同时也作为其分组key
     * @return java.util.List<org.elasticsearch.search.aggregations.support.ValuesSourceAggregationBuilder>
     * @author youli.chen
     * @since v1.0
     * @version v1.0
     */
    public CallLogAggsPojo sumMuchCallAttr4Total(IndexTypeEnum indexTypeEnum, BoolQueryBuilder boolQueryBuilder, List<String> sumFieldList) throws XbbException {
        List<ValuesSourceAggregationBuilder> aggsList = new ArrayList<>();
        for (String sumField : sumFieldList) {
            //聚合字段和聚合分组的key都使用sumField
            SumAggregationBuilder sumAggregationBuilder = AggregationBuilders.sum(sumField).field(sumField);
            aggsList.add(sumAggregationBuilder);
        }
        JSONObject jsonObject = esHelper.multElasticAggs4NoBuckets2Object(indexTypeEnum, boolQueryBuilder, aggsList);
        JSONObject aggregations = jsonObject.getJSONObject("aggregations");
        Double durationCount = aggregations.getJSONObject("duration").getBigDecimal("value").doubleValue();
        Double callCount = jsonObject.getBigDecimal("total").doubleValue();
        CallLogAggsPojo aggsPojo = new CallLogAggsPojo();
        aggsPojo.setCallCount(callCount);
        aggsPojo.setDurationCount(durationCount);
        return aggsPojo;
    }
}
